package com.cskaoyan.shopping.service.impl.zxw;


import com.cskaoyan.shopping.converter.CartItemConverter;
import com.cskaoyan.shopping.dal.entitys.Item;
import com.cskaoyan.shopping.dal.persistence.ItemCatMapper;
import com.cskaoyan.shopping.dal.persistence.ItemMapper;
import com.cskaoyan.shopping.dto.CartProductDto;
import com.cskaoyan.shopping.form.CartRequest;
import com.cskaoyan.shopping.form.CheckAllItemRequest;
import com.cskaoyan.shopping.service.ICartService;
import com.cskaoyan.shopping.service.ZxwICartService;
import org.redisson.api.RMap;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.validation.constraints.NotNull;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 * @author 曾添乐啦
 * @since 2023/01/09 22:08
 */
@Service
public class ZxwICartServiceImpl implements ZxwICartService {

    @Autowired
    ItemMapper itemMapper;

    @Autowired
    ItemCatMapper itemCatMapper;

    @Autowired
    CartItemConverter cartItemConverter;

    //Redis缓存客户端
    @Autowired
    RedissonClient redissonClient;

    /**
     * 用户信息    →   存在请求头或者cookie里
     * 购物车信息  →   存在Redis缓存里
     * <p>
     * RedissonClient客户端
     * Redis命令和Redisson对象匹配列表
     * Github官方文档参考链接：一般打不开
     * // https://github.com/redisson/redisson/wiki/11.-redis%E5%91%BD%E4%BB%A4%E5%92%8Credisson%E5%AF%B9%E8%B1%A1%E5%8C%B9%E9%85%8D%E5%88%97%E8%A1%A8
     * 华为开发者联盟Redisson参考文档链接     →    有Redisson使用的参考代码
     * https://huaweicloud.csdn.net/637ee63cdf016f70ae4c8fe7.html?spm=1001.2101.3001.6650.16&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7Eactivity-16-125536050-blog-126452291.pc_relevant_3mothn_strategy_and_data_recovery&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7Eactivity-16-125536050-blog-126452291.pc_relevant_3mothn_strategy_and_data_recovery&utm_relevant_index=17
     * <p>
     * 购物车的存储
     * 回忆Redis中的几种数据结构
     * <p>
     * String    →      key-value
     * <p>
     * list      →      1、有序 2、可重复
     * <p>
     * hash      →      相当于map，可以存储多个键值对
     * <p>
     * set       →      1、无序 2、不可重复
     * <p>
     * zset      →      每一个member都有一个自己的score
     * <p>
     * 1、如果使用string存储，那么key：userId,value：list<ProductDTO>(转json)
     * <p>
     * 2、如果使用list，没有必要
     * <p>
     * 3、如果使用set，set最大的特点是求集合的交集、并集、差集
     * <p>
     * 4、如果使用zset
     * <p>
     * 5、在项目中可以选择string和hash来存储，推荐使用hash
     * <p>
     * <p>
     * key:  用户Id  （相当于数据库中的表）
     * field:商品id  （相当于数据库中列名）
     * value：该商品详情（购物车商品对象）com.cskaoyan.order.dto.CartProductDto（相当于数据库列名对应的属性值）
     * <p>
     * <p>
     * 各个网站购物车存储位置不一样：
     * 京东存在前端的cookie
     *
     * @author 曾添乐啦
     * @since 2023/01/09 20:59
     */
    //获得购物车列表
    @Override
    public List<CartProductDto> getCartListById(Long userId) {
        List<CartProductDto> cartProductDtos = new ArrayList<>();
        //从Redis缓存中获取购物车商品数据
        //购物车里有一堆商品，使用hash要比使用string处理起来更简单
        //字符串
        //RBucket<Object> bucket = redissonClient.getBucket(userId.toString());
        //Object value = bucket.get();
        //hash
        RMap<String, CartProductDto> map = redissonClient.getMap(userId.toString());
        Collection<CartProductDto> values = map.values();
        for (CartProductDto value : values) {
            cartProductDtos.add(value);
        }
        return cartProductDtos;
    }

    /**
     * 添加商品到购物车
     * 商品是否为同一商品：
     * 是同一商品，需要合并，只更新数量
     * 不是同一商品，直接添加
     * 请求参数：{"userId":"62","productId":100053202,"productNum":1,"checked":true}
     * 响应参数：{
     * "success":true,
     * "message":"success",
     * "code":200,
     * "result":"成功",
     * "timestamp":1587794143256
     * }
     *
     * @author 曾添乐啦
     * @since 2023/01/09 20:59
     */
    //添加商品到购物车
    @Override
    public void addToCart(CartRequest request) {

        //获取用户信息
        @NotNull
        Long userId = request.getUserId();
        //获取该用户的购物车列表
        RMap<String, CartProductDto> map = redissonClient.getMap(userId.toString());
        //获取该商品的id
        @NotNull
        Long productId = request.getProductId();
        //获取该商品的状态
        String checked = request.getChecked();
        //获取用户购物车未添加商品时，该商品的数量
        Integer productNumBeforeAdd = request.getProductNum();
        //判断购物车中新添加的商品是否已经存在
        //如果商品已经存在
        //更新该商品数量
        if (map.containsKey(productId)) {
            //获取执行添加操作时增加的商品数量
            CartProductDto cartProductDto = map.get(productId);
            Long productNumNewAdd = cartProductDto.getProductNum();
            //执行完添加操作之后商品的数量
            Long productNum = productNumBeforeAdd + productNumNewAdd;
            cartProductDto.setProductNum(productNum);
            map.put(productId.toString(), cartProductDto);
        }
        //如果该商品不在购物车，则购物车商品表中没有该商品数据
        //查询该商品信息
        Item item = itemMapper.selectByPrimaryKey(productId);

        //类型转化
        CartProductDto cartProductDto = cartItemConverter.item2Dto(item);
        //存回Redis缓存
        cartProductDto.setProductNum(productNumBeforeAdd.longValue());
        cartProductDto.setChecked(checked);
        map.put(productId.toString(),cartProductDto);
    }

    /**
     * 更新购物车中的商品
     * 购物车需要更新的就只有商品状态和商品数量
     * <p>
     * 请求参数：{userId: "62", productId: 100053312, productNum: 3, checked: "true"}
     * 响应参数：{"success":true,"message":"success","code":200,"result":"成功","timestamp":1587794411224}
     *
     * @author 曾添乐啦
     * @since 2023/01/09 20:59
     */
    //更新购物车中的商品
    @Override
    public void updateCartNum(CartRequest request) {
        //从Redis缓存中获取购物车商品数据
        //获取用户信息
        @NotNull
        Long userId = request.getUserId();
        RMap<String, CartProductDto> map = redissonClient.getMap(userId.toString());
        @NotNull
        Long productId = request.getProductId();
        //获取商品id对应的商品信息
        CartProductDto cartProductDto = map.get(productId.toString());
        //获取商品状态
        String checked = request.getChecked();
        //获取商品数量
        Integer productNum = request.getProductNum();
        //更新购物车中该商品数据:商品数量是否增加，商品是否被勾选选中
        //存回Redis缓存
        cartProductDto.setChecked(checked);
        cartProductDto.setProductNum(productNum.longValue());
        map.put(productId.toString(), cartProductDto);

    }

    @Override
    public void checkAllCartItem(CheckAllItemRequest request) {

    }

    @Override
    public void deleteCartItem(Long uid, Long itemId) {

    }

    @Override
    public void deleteCheckedItem(Long userId) {

    }
}
